﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Threading;

namespace BoAddonBiz_FreightForwarder.ObjectFind
{
    class B1Form_ObjectFind : SAPBoAddon.B1Form
    {
        #region private
        private Thread thread;
        private ObjectFind oFind;
        #endregion
        #region override
        protected override bool BeforeSaveCheckFormData()
        {
            return true;
        }

        protected override void FormEditModeChange(SAPBoAddon.frmItemEditMode frmEditMode)
        {

        }

        protected override void FormInfoSetting(SAPBoAddon.B1FormSetting FormSetting)
        {
            this.FormSetting.FormType = B1FormTypes.ado_AVA_ObjectFind;
            this.FormSetting.FormFileName = B1FormTypes.ado_AVA_ObjectFind + "Form.srf";
        }

        protected override void InitializeForm(SAPBoAddon.B1FormInitializePar InitPar)
        {
            string ObjectType = InitPar.KeyValue;
            SAPbobsCOM.Recordset ors;
            string SQL = string.Empty;
            SAPbouiCOM.Grid oGrid;
            SAPbouiCOM.DataTable dt = default(SAPbouiCOM.DataTable);
            bool DataExists = false;

            dt = CurrentFormEx.DataSources.DataTables.Add("dt");
            oGrid = CurrentFormEx.Items.Item("Grid").Specific;
            ors = SBOCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.BoRecordset);
            #region 加载数据
            SQL = @"SELECT COUNT('A')
                                    FROM [@AVA_FIND] T0
	                                    INNER JOIN [@AVA_FIND1] T1 ON T0.DocEntry = T1.DocEntry
                                    Where T0.U_UserCode = '" + SBOCompany.UserSignature.ToString() + "' And T0.U_ObjectCode = '" + ObjectType + "'";
            ors.DoQuery(SQL);
            if (ors.Fields.Item(0).Value > 0)
            {
                //数据存在
                SQL = @"SELECT T1.U_TableName TableName,T1.U_Field Field,T1.U_FieldName FieldName,T1.U_IsFind IsFind,T1.U_IsDisplay IsDisplay,T1.U_Alias Alias,U_DataType DataType,U_SizeId SizeID,T1.U_IsMaster Master
                            FROM [@AVA_FIND] T0
	                            INNER JOIN [@AVA_FIND1] T1 ON T0.DocEntry = T1.DocEntry
                            Where T0.U_UserCode = '" + SBOCompany.UserSignature.ToString() + "' And T0.U_ObjectCode = '{0}'";
                DataExists = true;
            }
            else
            {
                #region 系统表
                //数据不存在
                SQL = @"
                                SELECT * 
                                INTO #Table1
                                FROM (
                                    SELECT top 1 '[@'+T0.TableName+']' TableName,'DocEntry' Field,'流水号' FieldName,Cast('N' as char(1)) IsFind,Cast('N' as char(1)) IsDisplay,T0.TableName + '.DocEntry' Alias,'A' DataType,8 SizeID,'Y' Master
                                    FROM OUDO T0
                                        INNER JOIN CUFD T2 ON ('@'+T0.TableName) = T2.TableID
                                    Where Not T2.TypeID in ('M') And T0.Code = '{0}' 
                                    UNION ALL
                                    SELECT '[@'+T0.TableName+']' TableName,'U_'+T2.AliasID Field,T2.Descr FieldName,Cast('N' as char(1)) IsFind,Cast('N' as char(1)) IsDisplay,T0.TableName + '.' + T2.AliasID Alias,T2.TypeID DataType,T2.SizeID,'Y' Master
                                    FROM OUDO T0
                                        INNER JOIN CUFD T2 ON ('@'+T0.TableName) = T2.TableID
                                    Where Not T2.TypeID in ('M') And T0.Code = '{0}' 
                                ) T0
                                Order By T0.TableName,T0.Field     

                                SELECT '[@'+T1.TableName+']' TableName,'U_'+T2.AliasID Field,T2.Descr FieldName,Cast('N' as char(1)) IsFind,Cast('N' as char(1)) IsDisplay,T1.TableName + '.' + T2.AliasID Alias,T2.TypeID DataType,T2.SizeID,'N' Master
                                Into #Table2
                                FROM OUDO T0
	                                INNER JOIN UDO1 T1 ON T0.Code = T1.Code
	                                INNER JOIN CUFD T2 ON ('@' + T1.TableName) = T2.TableID
                                Where Not T2.TypeID in ('M') And T0.Code = '{0}' 
                                Order By TableName, Field
           
                                SELECT * FROM #Table1
                                UNION ALL
                                SELECT * FROM #Table2   ";
                #endregion
            }

            dt.ExecuteQuery(string.Format(SQL, ObjectType));
            #region 加载到类

            oFind = new ObjectFind();
            oFind.ObjectCode = InitPar.KeyValue;

            ObjectFindLine oFindLine;
            FieldAlternate oFieldAlternate;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                oFindLine = oFind.Lines.Add();
                oFindLine.TableName = dt.GetValue("TableName", i).ToString().Trim();
                oFindLine.Field = dt.GetValue("Field", i).ToString().Trim();
                oFindLine.FieldName = dt.GetValue("FieldName", i).ToString().Trim();
                oFindLine.Alias = dt.GetValue("Alias", i).ToString().Trim();
                oFindLine.Master = dt.GetValue("Master", i).ToString().Trim() == "Y" ? true : false;
                string DataType = dt.GetValue("DataType", i).ToString().Trim();
                int StringLenght = dt.GetValue("SizeID", i);
                #region 判断字段是否有备选项
                SQL = @"	SELECT T1.IndexID,T1.FldValue,T1.Descr 
	                            FROM CUFD T0
		                            INNER JOIN UFD1 T1 ON T0.TableID = T1.TableID And T0.FieldID = T1.FieldID
	                            Where T0.TableID = '{0}' And T0.AliasID = '{1}'";
                ors.DoQuery(string.Format(SQL, oFindLine.TableName.Substring(1, oFindLine.TableName.Length - 2), oFindLine.Field.Substring(2, oFindLine.Field.Length - 2)));
                for (int j = 0; j < ors.RecordCount; j++)
                {
                    DataType = "C";
                    oFindLine.DataType = FieldDataType.Enum;
                    oFieldAlternate = oFindLine.Alternates.Add();
                    oFieldAlternate.Index = ors.Fields.Item("IndexID").Value;
                    oFieldAlternate.Value = ors.Fields.Item("FldValue").Value;
                    oFieldAlternate.Descr = ors.Fields.Item("Descr").Value;
                    ors.MoveNext();
                }
                #endregion
                if (DataType == "B")
                {
                    oFindLine.DataType = FieldDataType.Int;
                }
                if (DataType == "A" && StringLenght != 1)
                {
                    oFindLine.DataType = FieldDataType.String;
                }
                if (DataType == "D")
                {
                    oFindLine.DataType = FieldDataType.DateTime;
                }
                oFindLine.SizeId = StringLenght;
                oFindLine.IsFind = dt.GetValue("IsFind", i).ToString().Trim() == "Y" ? true : false;
                oFindLine.IsDisplay = dt.GetValue("IsDisplay", i).ToString().Trim() == "Y" ? true : false;
            }
            #endregion
            if (DataExists && (bool)InitPar.parObject == false)
            {
                SBOApp.Forms.ActiveForm.Close();
                CreateFindForm(oFind.Lines.Tables, oFind.Lines.Wherefields);
                B1Form_ConditionForm.Find = oFind;
                return;
            }
            #region grid  setting
            oGrid.DataTable = dt;
            oGrid.Columns.Item(0).Editable = false;
            oGrid.Columns.Item(1).Editable = false;
            oGrid.Columns.Item(2).Editable = false;
            oGrid.Columns.Item(3).Type = SAPbouiCOM.BoGridColumnType.gct_CheckBox;
            oGrid.Columns.Item(4).Type = SAPbouiCOM.BoGridColumnType.gct_CheckBox;
            oGrid.Columns.Item(5).Visible = false;
            oGrid.Columns.Item(6).Visible = false;
            oGrid.Columns.Item(7).Visible = false;
            oGrid.Columns.Item(8).Visible = false;
            #endregion
            #endregion
        }
        #endregion
        #region constructor
        public B1Form_ObjectFind()
        {
            this.frm_ItemEvent += new SAPBoAddon.IB1FormEvents.B1ItemEventEventHandler(B1Form_ObjectFind_frm_ItemEvent);
        }
        #endregion
        #region events
        void B1Form_ObjectFind_frm_ItemEvent(SAPBoAddon.B1AddonBase.B1ItemEvent pVal, ref bool BubbleEvent)
        {
            if (pVal.BeforeAction == false)
            {
                //控件值发生变化
                if (pVal.ItemUID == "Grid" && pVal.EventType == SAPbouiCOM.BoEventTypes.et_CLICK)
                {
                    //grid
                    if (pVal.ColUID != null && pVal.Row >= 0 && (pVal.ColUID == "IsFind" || pVal.ColUID == "IsDisplay"))
                    {
                        UIChanged(pVal.ItemUID, pVal.ColUID, pVal.Row);
                    }
                }
                if (pVal.ItemUID == "save" && pVal.EventType == SAPbouiCOM.BoEventTypes.et_CLICK)
                {
                    if (oFind.Lines.Wherefields.Count <= 0 || oFind.Lines.fields.Count <= 0)
                    {
                        if (oFind.Lines.Wherefields.Count <= 0)
                        {
                            SBOApp.MessageBox("请选择查询的条件");
                            return;
                        }
                        if (oFind.Lines.fields.Count <= 0)
                        {
                            SBOApp.MessageBox("请选择显示的列");
                            return;
                        }
                    }
                    thread = new Thread(new ThreadStart(Save));
                    thread.Start();
                    CreateFindForm(oFind.Lines.Tables, oFind.Lines.Wherefields);
                    B1Form_ConditionForm.Find = oFind;
                    SBOApp.Forms.Item(pVal.FormUID).Close();
                }
                if (pVal.ItemUID == "cancel" && pVal.EventType == SAPbouiCOM.BoEventTypes.et_CLICK)
                {
                    SBOApp.Forms.ActiveForm.Close();
                }
            }
        }
        #endregion
        #region methods
        /// <summary>
        /// UI变化
        /// </summary>
        /// <param name="ItemUID"></param>
        /// <param name="ColUID"></param>
        /// <param name="row"></param>
        private void UIChanged(string ItemUID, string ColUID = null, int row = -1)
        {
            dynamic Value = default(dynamic);
            string TableName = string.Empty;
            string FieldName = string.Empty;
            SAPbouiCOM.Grid oGrid = CurrentFormEx.Items.Item(ItemUID).Specific;
            if (oGrid.Columns.Item(ColUID).Type == SAPbouiCOM.BoGridColumnType.gct_CheckBox)
            {
                TableName = oGrid.DataTable.GetValue("TableName", row);
                FieldName = oGrid.DataTable.GetValue("Field", row);
                Value = oGrid.DataTable.GetValue(ColUID, row);
            }
            ObjectFindLine oFindLine = oFind.GetObjectFindLine(TableName, FieldName);
            oFindLine.GetType().GetProperty(ColUID).SetValue(oFindLine, Value == "Y" ? true : false, null);
        }
        #region 创建窗体
        /// <summary>
        /// 自动创建查询窗体
        /// </summary>
        /// <param name="ofields"></param>
        private void CreateFindForm(ObjectFindLines.tables tables, ObjectFindLines.wherefields fields)
        {
#if DEBUG
            DateTime CurrentDatetime = DateTime.Now;
#endif
            string XmlPath = System.Windows.Forms.Application.StartupPath + @"\Form\TemplateForm.srf";
            int client_height = 80;
            int height = 107;
            #region 读取模板窗体控件
            XmlDocument xmlfile = new XmlDocument();
            xmlfile.Load(XmlPath);
            XmlNode lblName = xmlfile.SelectSingleNode("//item[@uid='lblName_']");
            XmlNode Txt1 = xmlfile.SelectSingleNode("//item[@uid='txt1_']");
            XmlNode lblTo = xmlfile.SelectSingleNode("//item[@uid='lblTo_']");
            XmlNode Txt2 = xmlfile.SelectSingleNode("//item[@uid='txt2_']");
            #endregion
            #region 创建控件
            StreamWriter sw = File.CreateText(Path.GetDirectoryName(XmlPath) + @"\template.txt");
            foreach (XmlNode btn in xmlfile.SelectNodes("//item[@type='4']"))
            {
                sw.WriteLine(btn.OuterXml);
            }
            foreach (ObjectFindLines.wherefield field in fields)
            {
                height += 16;
                client_height += 16;
                sw.WriteLine(SetlblName(lblName, field.alias));
                if (field.DataType == FieldDataType.Enum)
                {
                    sw.WriteLine(SetCmb(Txt1, "F_" + field.Key, field.alternates));
                }
                else
                    sw.WriteLine(SetTxt(Txt1, "F_" + field.Key));
                SetUserDataSource(xmlfile, "F_" + field.Key, field.DataType, field.size.ToString());
                if (field.count == 2)
                {
                    sw.WriteLine(SetNode(lblTo, Txt1.Attributes["top"].Value));
                    sw.WriteLine(SetTxt(Txt2, "T_" + field.Key, Txt1.Attributes["top"].Value));
                    SetUserDataSource(xmlfile, "T_" + field.Key, field.DataType, field.size.ToString());
                }
            }
            sw.Flush();
            sw.Close();
            sw.Dispose();
            #endregion
            #region 读取处理好的XML字符串
            #region 移除模板节点
            XmlNode node = xmlfile.SelectSingleNode("//items/action");
            foreach (XmlNode oNode in xmlfile.SelectNodes("//items/action[@type='add']/item"))
            {
                node.RemoveChild(oNode);
            }
            #endregion
            StreamReader sr = new StreamReader(Path.GetDirectoryName(XmlPath) + @"\template.txt");
            node.InnerXml += sr.ReadToEnd();
            sr.Close();
            sr.Dispose();
            File.Delete(Path.GetDirectoryName(XmlPath) + @"\template.txt");
            #endregion
            #region 保存为查找窗体文件
            XmlPath = Path.GetDirectoryName(XmlPath) + @"\AVA_ConditionForm.srf";
            xmlfile.SelectSingleNode("//form[@title='查询条件']").Attributes["client_height"].Value = client_height.ToString();
            xmlfile.SelectSingleNode("//form[@title='查询条件']").Attributes["height"].Value = height.ToString();
            xmlfile.Save(XmlPath);
            #endregion
            SAPBoAddon.B1Assistant.Form.LoadToSBOApplciation(XmlPath, "");
#if DEBUG
            TimeSpan ts = DateTime.Now - CurrentDatetime;
            SBOApp.SetStatusBarMessage("调试运行时间：" + ts.TotalMilliseconds.ToString(), SAPbouiCOM.BoMessageTime.bmt_Short, false);

#endif
        }
        /// <summary>
        /// 设置结点的UID及TOP值
        /// </summary>
        /// <param name="Node"></param>
        private string SetNode(XmlNode Node, string top = null)
        {
            if (Node.Attributes["uid"].Value.Substring(Node.Attributes["uid"].Value.Length - 1, 1) == "_")
            {
                Node.Attributes["uid"].Value += "1";
            }
            else
            {
                string uid = Node.Attributes["uid"].Value;
                uid = uid.Substring(0, uid.IndexOf("_") + 1) + (int.Parse(uid.Substring((uid.IndexOf("_") + 1), uid.Length - (uid.IndexOf("_") + 1))) + 1).ToString();
                Node.Attributes["uid"].Value = uid;
                Node.Attributes["top"].Value = (decimal.Parse(Node.Attributes["top"].Value) + 16).ToString();
            }
            if (!string.IsNullOrEmpty(top))
            {
                Node.Attributes["top"].Value = top;
            }
            return Node.OuterXml;
        }
        /// <summary>
        /// 设置字段的名称
        /// </summary>
        /// <param name="lblName"></param>
        /// <param name="Name"></param>
        private string SetlblName(XmlNode lblName, string Name)
        {
            SetNode(lblName);
            lblName.SelectSingleNode("specific").Attributes["caption"].Value = Name;
            return lblName.OuterXml;
        }
        /// <summary>
        /// 设置文本
        /// </summary>
        /// <param name="Txt"></param>
        /// <param name="TableName"></param>
        /// <param name="FieldName"></param>
        private string SetTxt(XmlNode Txt, string FieldName, string top = null)
        {
            SetNode(Txt, top);
            Txt.SelectSingleNode("specific/databind").Attributes["databound"].Value = "1";
            Txt.SelectSingleNode("specific/databind").Attributes["alias"].Value = FieldName;

            return Txt.OuterXml;
        }
        private string SetCmb(XmlNode cmb, string FieldName, FieldAlternates Alternates, string top = null)
        {
            SetNode(cmb, top);
            cmb.Attributes["type"].Value = "113";
            cmb.Attributes["disp_desc"].Value = "1";
            cmb.SelectSingleNode("specific/databind").Attributes["databound"].Value = "1";
            cmb.SelectSingleNode("specific/databind").Attributes["alias"].Value = FieldName;
            cmb.SelectSingleNode("specific").InnerXml += "<ValidValues><action type=\"add\"></action></ValidValues>";
            cmb.SelectSingleNode("specific/ValidValues/action").InnerXml = "<ValidValue value=\"\" description=\"\" />";
            foreach (FieldAlternate Alternate in Alternates)
            {
                cmb.SelectSingleNode("specific/ValidValues/action").InnerXml += "<ValidValue value=\"" + Alternate.Value + "\" description=\"" + Alternate.Descr + "\" />";
            }
            string OuterXml = cmb.OuterXml;
            cmb.Attributes["type"].Value = "16";
            cmb.Attributes["disp_desc"].Value = "0";
            XmlNode oNode = cmb.SelectSingleNode("specific/ValidValues");
            cmb.SelectSingleNode("specific").RemoveChild(oNode);
            return OuterXml;
        }
        /// <summary>
        /// 设置窗体的用户自定义数据
        /// </summary>
        /// <param name="node"></param>
        /// <param name="FieldName"></param>
        /// <param name="DataType"></param>
        private void SetUserDataSource(XmlDocument node, string FieldName, FieldDataType DataType, string size)
        {
            switch (DataType)
            {
                case FieldDataType.String:
                    node.SelectSingleNode("//userdatasources/action[@type='add']").InnerXml += "<datasource uid=\"" + FieldName + "\" type=\"9\" size=\"" + size + "\" />";
                    break;
                case FieldDataType.Int:
                    node.SelectSingleNode("//userdatasources/action[@type='add']").InnerXml += "<datasource uid=\"" + FieldName + "\" type=\"2\" size=\"" + size + "\" />";
                    break;
                case FieldDataType.DateTime:
                    node.SelectSingleNode("//userdatasources/action[@type='add']").InnerXml += "<datasource uid=\"" + FieldName + "\" type=\"10\" size=\"" + size + "\" />";
                    break;
                case FieldDataType.Enum:
                    node.SelectSingleNode("//userdatasources/action[@type='add']").InnerXml += "<datasource uid=\"" + FieldName + "\" type=\"9\" size=\"" + size + "\" />";
                    break;
            }
        }
        #endregion
        private void Save()
        {
            string SQL = string.Empty;
            SAPbobsCOM.Recordset rs;
            int DocEntry;
            int LineId;
            try
            {
                rs = SBOCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.BoRecordset);
                if (SBOCompany.InTransaction == false) SBOCompany.StartTransaction();
                SQL = "SELECT COUNT('A') FROM [@AVA_FIND] Where U_UserCode = '" + SBOCompany.UserSignature.ToString() + "' And U_ObjectCode = '" + oFind.ObjectCode + "'";
                rs.DoQuery(SQL);
                if (rs.Fields.Item(0).Value > 0)
                {
                    SQL = "SELECT DocEntry FROM [@AVA_FIND] Where U_UserCode = '" + SBOCompany.UserSignature.ToString() + "' And U_ObjectCode = '" + oFind.ObjectCode + "'";
                    rs.DoQuery(SQL);
                    DocEntry = rs.Fields.Item("DocEntry").Value;
                    //更改
                    foreach (ObjectFindLine line in oFind.Lines)
                    {
                        SQL = "SELECT COUNT('A') FROM [@AVA_FIND1] Where U_TableName = '" + line.TableName + "' And U_Field = '" + line.Field + "'";
                        rs.DoQuery(SQL);
                        if (rs.Fields.Item(0).Value > 0)
                        {
                            SQL = "UPDATE [@AVA_FIND1] SET U_IsFind = '{0}',U_IsDisplay = '{1}',U_IsMaster = '{2}' Where U_TableName = '{3}' And U_Field = '{4}'";
                            rs.DoQuery(string.Format(SQL, line.IsFind ? "Y" : "N", line.IsDisplay ? "Y" : "N", line.Master ? "Y" : "N", line.TableName, line.Field));
                        }
                        else
                        {
                            SQL = "SELECT Max(LineId)+1 LineId FROM [@AVA_FIND1] Where DocEntry = " + DocEntry;
                            rs.DoQuery(SQL);
                            LineId = rs.Fields.Item("LineId").Value;
                            InsertChildTable(rs, line, DocEntry, LineId);
                        }
                    }
                }
                else
                {
                    //添加
                    SQL = "SELECT AutoKey FROM ONNM Where ObjectCode = 'AVA_Find'";
                    rs.DoQuery(SQL);
                    DocEntry = rs.Fields.Item("AutoKey").Value;
                    SQL = "INSERT INTO [@AVA_FIND] (DocEntry,Object,U_UserCode,U_ObjectCode,U_ObjectName) Values ({0},'{1}','{2}','{3}','{4}')";
                    rs.DoQuery(string.Format(SQL, DocEntry, "AVA_Find", SBOCompany.UserSignature.ToString(), oFind.ObjectCode, oFind.ObjectName));
                    LineId = 1;
                    foreach (ObjectFindLine line in oFind.Lines)
                    {
                        InsertChildTable(rs, line, DocEntry, LineId);
                        LineId++;
                    }
                    SQL = "UPDATE ONNM SET AutoKey = " + (DocEntry + 1).ToString() + " Where ObjectCode = 'AVA_Find'";
                    rs.DoQuery(SQL);
                }
                if (SBOCompany.InTransaction) SBOCompany.EndTransaction(SAPbobsCOM.BoWfTransOpt.wf_Commit);
                thread.Abort();
            }
            catch (Exception ex)
            {
                if (SBOCompany.InTransaction) SBOCompany.EndTransaction(SAPbobsCOM.BoWfTransOpt.wf_RollBack);
                throw (ex);
            }
        }
        private void InsertChildTable(SAPbobsCOM.Recordset rs, ObjectFindLine line, int DocEntry, int LineId)
        {
            string SQL = "INSERT INTO [@AVA_FIND1] (DocEntry,LineId,U_TableName,U_Field,U_FieldName,U_Alias,U_IsFind,U_IsDisplay,U_IsMaster,U_DataType,U_SizeId) Values ({0},{1},'{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}',{10})";
            string DataType = string.Empty;
            switch (line.DataType)
            {
                case FieldDataType.Int:
                    DataType = "B";
                    break;
                case FieldDataType.String:
                    DataType = "A";
                    break;
                case FieldDataType.DateTime:
                    DataType = "D";
                    break;
                case FieldDataType.Enum:
                    DataType = "C";
                    break;
            }

            rs.DoQuery(string.Format(SQL, DocEntry, LineId, line.TableName, line.Field, line.FieldName, line.Alias, line.IsFind ? "Y" : "N", line.IsDisplay ? "Y" : "N", line.Master ? "Y" : "N", DataType, line.SizeId));
        }
        #endregion
    }
}
